package org.weasel.unittests;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Time;
import java.util.ArrayList;

import junit.framework.TestCase;

import org.weasel.business.Developer;
import org.weasel.business.Iteration;
import org.weasel.business.Project;
import org.weasel.business.Release;
import org.weasel.business.Task;
import org.weasel.business.Unscheduled;
import org.weasel.business.UserStory;
import org.weasel.data.ProjectManager;

public class ProjectManagerTest extends TestCase {
	private final String xmlFileLoc = "./testfolder/ProjectManagerTest.xml";
	private Project p;
	private ProjectManager man;
	private ArrayList<Developer> allDevelopers;
	private Developer developer;
	
	@Override
	protected void setUp() throws Exception {
		super.setUp();
		//have to reset XML file; it will then be created by the ProjectManager class
//		if(Utilities.existsFile(xmlFileLoc)) Utilities.deleteFile(xmlFileLoc); //<-- doesn't work! strange??
		resetXMLFile();
		developer = new Developer("9999999", "developer", "mail", "position");
		allDevelopers = new ArrayList<Developer>();
		allDevelopers.add(developer);
		p = new Project("123456", "myproject", xmlFileLoc, allDevelopers);
		man = new ProjectManager(p);
	}

	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
		p = null;
		man = null;
		allDevelopers = null;
		developer = null;
	}

	/**
	 * Create an release and check afterwards if it has been
	 * put in the XML-file by using the appropriate get-method of the dataManager
	 * So it tests both, the creation and retrieval of the object
	 * @throws Exception 
	 */
	public void testCreate_GetRelease() throws Exception {
		Release r = man.createRelease("1st release");
		//release r should now be in the XML file so query for it
		
		Release rCheck = man.getRelease(r.getId());
		
		assertEquals("Expected release-id " + r.getId(), r.getId(), rCheck.getId());
		assertEquals("Expected release-name '1st release'", r.getName(), rCheck.getName());
		//check if unscheduled object has been attached properly
		assertEquals("True, which means UnscheduledObject is != null", true, r.getUnscheduled()!=null);
	}

	/**
	 * Creates and then deletes a release and checks if it is not present
	 * in the XML-file. That is the case when an Exception is thrown, since
	 * an XML Element cannot be retrieved --> means not present
	 * @throws Exception
	 */
	public void testDeleteRelease() throws Exception {
		boolean ok = false;
		Release r = man.createRelease("1st release");
		
		//remove it from the XML again
		man.deleteRelease(r.getId());
		
		try{
			//try to retrieve it from DB
			man.getRelease(r.getId());
		}catch(NullPointerException e){
			ok = true;
		}
		
		assertEquals(true, ok);
	}
	
	public void testGetReleases() throws Exception{
		Release r = man.createRelease("1st release");
		Release r2 = man.createRelease("2nd release");
		Release r3 = man.createRelease("3rd release");
		
		ArrayList<Release> releases = man.getReleases();
		
		assertEquals("expected size 3", 3, releases.size());
		assertEquals("expected 1st element with id " + r.getId(), r.getId(), releases.get(0).getId());
		assertEquals("expected 2nd element with id " + r2.getId(), r2.getId(), releases.get(1).getId());
		assertEquals("expected 3rd element with id " + r3.getId(), r3.getId(), releases.get(2).getId());
	}

	/**
	 * Create an Iteration and check afterwards if it has been
	 * put in the XML-file by using the appropriate get-method of the dataManager
	 * So it tests both, the creation and retrieval of the object
	 * @throws Exception 
	 */
	public void testCreate_GetIteration() throws Exception {
		Release r = man.createRelease("1st release");
		Iteration i = man.createIteration(r.getId(), "my 1st iteration");
		
		//try to read from XML
		Iteration iCheck = man.getIteration(i.getId());
		
		assertEquals(i.getId(), iCheck.getId());
		assertEquals(i.getName(), iCheck.getName());
	}

	/**
	 * Creates and then deletes an iteration and checks if it is not present
	 * in the XML-file. That is the case when an Exception is thrown, since
	 * an XML Element cannot be retrieved --> means not present
	 * @throws Exception
	 */
	public void testDeleteIteration() throws Exception {
		boolean ok = false;
		Release r = man.createRelease("1st release");
		Iteration i = man.createIteration(r.getId(), "my 1st iteration");
		
		man.deleteIteration(i.getId());
		
		try{
			man.getIteration(i.getId());
		}catch(NullPointerException e){
			ok = true;
		}
		assertEquals(true, ok);
	}

	
	/**
	 * Create an Iteration and check afterwards if it has been
	 * put in the XML-file by using the appropriate get-method of the dataManager
	 * So it tests both, the creation and retrieval of the object
	 * Here the UserStory is created in the list of a specific iteration; this is
	 * done by passing it the iteration-id
	 * @throws Exception 
	 */
	public void testCreate_GetUserStory() throws Exception{
		boolean ok = false;
		Release r = man.createRelease("1st release");
		Iteration i = man.createIteration(r.getId(), "my 1st iteration");
		UserStory story = man.createUserStory(i.getId(), "storyName", 5, Time.valueOf("01:00:00"), Time.valueOf("00:30:00"), 5);
		
		//retrieve the Iteration "i" from the XML-file. The object should contain
		//the inserted story
		Iteration iCheck = man.getIteration(i.getId());
		ArrayList<UserStory> stories = iCheck.getUserStories();
		for (UserStory st : stories) {
			if(st.getId().equals(story.getId())) {
				ok = true;
			}
		}
		assertEquals("Checks if the userstory has been correctly attached to the iteration", true,ok);
	}

	/**
	 * Creates and then deletes a UserStory and checks if it is not present
	 * in the XML-file. That is the case when an Exception is thrown, since
	 * an XML Element cannot be retrieved --> means not present
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	public void testDeleteUserStory() throws Exception {
		boolean ok = false;
		UserStory story = man.createUserStory("storyName", 5, Time.valueOf("01:00:00"), Time.valueOf("00:30:00"), 5);

		
		man.deleteUserStory(story.getId());
		
		try{
			man.getUserStory(story.getId());
		}catch(NullPointerException e){
			//if it fails...it got deleted since the getUserStoryElement fails to read the XML Tag
			ok = true;
		} 
		assertEquals(true, ok);
	}
	
	public void testGetDeveloperIDs() throws Exception {
		man.addDeveloper(developer.getId());
		int sizeOfList = man.getDeveloperIDs().size();
		assertEquals("Size of the list should be one.", 1, sizeOfList);
		assertEquals("The id of the global developer and the from the list must be the same.", developer.getId(), man.getDeveloperIDs().get(0));
	}
	
	/**
	 * Create a developer and check afterwards if it has been
	 * put in the XML-file by using the appropriate get-method of the dataManager
	 * So it tests both, the creation and retrieval of the object
	 * 
	 * @throws Exception 
	 */
	public void testAddDeveloper() throws Exception {
		man.addDeveloper(developer.getId());
		
		//check if Developer has been created
		assertTrue(man.getDeveloperIDs().contains(developer.getId()));
	}
	
	/**
	 * Creates and then deletes a developer and checks if it is not present
	 * in the XML-file. That is the case when an Exception is thrown, since
	 * an XML Element cannot be retrieved --> means not present
	 * @throws Exception
	 */
	public void testDeleteDeveloper() throws Exception{
		man.deleteDeveloper(developer.getId());
		
		assertFalse(man.getDeveloperIDs().contains(developer.getId()));
	}
	
	/**
	 * Create a task and check afterwards if it has been
	 * put in the XML-file by using the appropriate get-method of the dataManager
	 * So it tests both, the creation and retrieval of the object
	 * 
	 * @throws Exception 
	 */
	@SuppressWarnings("deprecation")
	public void testCreate_GetTask() throws Exception{
		UserStory story = man.createUserStory("storyName", 5, Time.valueOf("01:00:00"), Time.valueOf("00:30:00"), 5);
		Task t = man.createTask(story.getId(), "this is a test-task");
		//check if it has been added
		Task tCheck = man.getTask(t.getId());
		
		assertEquals("Checks the id of the inserted with the retrieved Task!", t.getId(), tCheck.getId());
		assertEquals("Checks the description of the inserted with the retrieved Task", t.getDescription(), tCheck.getDescription());
	}
	
	/**
	 * Creates and then deletes a task and checks if it is not present
	 * in the XML-file. That is the case when an Exception is thrown, since
	 * an XML Element cannot be retrieved --> means not present
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	public void testDeleteTask() throws Exception{
		boolean ok = false;
		UserStory story = man.createUserStory("storyName", 5, Time.valueOf("01:00:00"), Time.valueOf("00:30:00"), 5);
		Task t = man.createTask(story.getId(), "this is a test-task");
		
		man.deleteTask(t.getId());
		
		try{
			man.getTask(t.getId());
		}catch(NullPointerException e){
			ok = true;
		}
		
		assertEquals("expected true since object shouldn't be present", true, ok);
	}
	
	
	public void testCreate_GetUnscheduled() throws Exception{
		Release r = man.createRelease("1st release");
		Unscheduled unsch = man.createUnscheduled(r.getId());
		
		Unscheduled unschCheck = man.getUnscheduled(unsch.getId());
		
		assertEquals("Expected unscheduled object with id " + unsch.getId(), unsch.getId(), unschCheck.getId());
	}
	
	/**
	 * Unscheduled method ONLY used to load unscheduled part of the project at set-up
	 * @throws Exception 
	 *
	 */
	public void testGetProjectUnscheduled() throws Exception{
//		Unscheduled unsch = man.createUnscheduled(p.getId());
		String unschId = "31411407294223"; //the same as in the unscheduled element in the resetXMLFile() method
		Unscheduled unschCheck = man.getUnscheduled();
		
		assertEquals("Expected unscheduled object with id " + unschId, unschId, unschCheck.getId());
	}
	
	/**
	 * create basic structure of the XML-file for testing
	 * @throws IOException
	 */
	private void resetXMLFile() throws IOException{
		String xmlFileContent = "" +
				"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" +
				"	<project>\n" +
				"		<id>123456</id>" +
				"		<developers></developers>\n" +
				"		<releases></releases>\n" +
//				"		<release>\n" + 
//				"			<iteration>\n" +
//				"			</iteration>\n" +
//				"		</release>" +
				"		<unscheduled>\n" +
				"			<id>31411407294223</id>\n" +
				"			<userstories></userstories>\n" +
				"		</unscheduled>\n" +
				"	</project>";
		
		//create file writer that doesn't append on the file
		FileWriter f = new FileWriter(xmlFileLoc, false);
		PrintWriter out = new PrintWriter(f); 
		out.println(xmlFileContent);
		out.close();
		f.close();
	}
}
